/*
 * This file is part of SSHTTPD.
 * 
 * SSHTTPD is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * SSHTTPD is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @file
 * Implements file/data access and information collecting routines. 
 */

/* Application level includes. */
#include "include/file.h"
#include "include/utils.h"

/* System level includes. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/**
 * Gets the size of a file on disk.
 * @param file File desriptor
 * @return The file size in bytes.
 */
static int fsize(FILE *file) {
	int size;
	int cur;
	
	size = 0;
	cur = ftell(file);
	
	fseek(file, 0, SEEK_END);
	size = ftell(file);
	fseek(file, cur, SEEK_SET);
	
	return size;
}

/**
 * Gets the mime content-type of a file based on its file extention.
 * @param url String to parse, ie "/index.html" or "/image.png".
 * @return The content-type of the file, needs to be free()'d.
 */ 
static char *getctype(const char *url) {
	char *ext = strrchr(url, '.') + 1;
	char *str = NULL;
	
	if(strstr(ext, "html") != NULL)
		str = heapstr("text/html");
	else if(strstr(ext, "gif") != NULL)
		str = heapstr("image/gif");
	else if(strstr(ext, "jpg") != NULL)
		str = heapstr("image/jpg");
	else if(strstr(ext, "htm") != NULL)
		str = heapstr("text/html");
	else if(strstr(ext, "png") != NULL)
		str = heapstr("image/png");
	
	return str;
}

/** *TEMP* path of the webservers content dir. */
#define PATH "www" 
/** Maximum size of PATH + URL. */ 
#define PMAX 128
mfile_t *newfile(char *data, char *ctype, int size) {
	mfile_t *file;
	
	if(!(file = malloc(sizeof *file))) {
		event(EPROB, "malloc() in newfile()");
		return NULL;
	}
	
	file->data = heapstr(data);
	file->ctype = heapstr(ctype);
	file->size = size;
	file->nf = 0;
	
	return file;
}

void destroyfile(mfile_t *file) {
	free(file->data);
	free(file->ctype);
	free(file);
}

mfile_t *getfile(const char *url, int pretend) {
	FILE *file;
	mfile_t *mfile;
	char path[PMAX] = PATH;
	
	/* Stores the requested URL with the reletive path prepended to it. */
	strncat(path, url, PMAX-strlen(PATH));
	
	/* Try to open the file. If we can, store it in a buffer.*/
	file = fopen(path, "rb");
	
	if(file != NULL) {
		if((mfile = newfile(NULL, NULL, fsize(file))) == NULL)
			return NULL;

		mfile->ctype = getctype(url);  /*Avoid newfiles memory alloc for ctype by manual asssign. */ 
		
		/* If we are pretending we return without reading the data. */
		if(pretend) {
			event(ELOG, "found file %s on disk", url);
			fclose(file);
			return mfile;
		}
		
		/* Allocate the buffer and copy our file into it. */
		if(!(mfile->data = malloc(mfile->size))) {
			event(EPROB, "malloc() in getfile()");
			destroyfile(mfile);
			return NULL;
		}
		
		memset(mfile->data, '\0', mfile->size);
		fread(mfile->data, 1, mfile->size, file);
		fclose(file);
		event(ELOG, "retrieved file %s from disk", path);
		
		return mfile;
	}	
	
	/* No date to retreive. */
	event(ELOG, "could not retrieve %s from disk", path);
	return NULL;
}

